// SPDX-FileCopyrightText: Adam Evyčędo
//
// SPDX-License-Identifier: AGPL-3.0-or-later

package api

import (
	"apiote.xyz/p/szczanieckiej/traffic"

	"time"

	"golang.org/x/text/language"
)

type AcceptVersionError struct{}

func (e AcceptVersionError) Error() string {
	return ""
}

var AcceptError AcceptVersionError

func selectLanguage(descriptions, attributions map[string]string, preferredLanguages []language.Tag) (language.Tag, language.Tag) {
	descriptionTags := []language.Tag{}
	for t := range descriptions {
		descriptionTags = append(descriptionTags, language.MustParse(t)) // NOTE tag is internally stringified, must parse
	}
	attributionTags := []language.Tag{}
	for t := range attributions {
		attributionTags = append(attributionTags, language.MustParse(t)) // NOTE tag is internally stringified, must parse
	}

	matcher := language.NewMatcher(preferredLanguages)
	_, index, _ := matcher.Match(descriptionTags...)
	descriptionTag := preferredLanguages[index]
	_, index, _ = matcher.Match(attributionTags...)
	attributionTag := preferredLanguages[index]

	return descriptionTag, attributionTag
}

func selectLanguageByTag(messages map[language.Tag]string, preferredLanguages []language.Tag) language.Tag {
	tags := []language.Tag{}
	for t := range messages {
		tags = append(tags, t)
	}

	matcher := language.NewMatcher(preferredLanguages)
	_, index, _ := matcher.Match(tags...)
	return preferredLanguages[index]
}

func MakeFeedsResponse(feedInfos map[string]traffic.FeedInfo, lastUpdates map[string]time.Time, accept map[uint]struct{}, preferredLanguages []language.Tag) (FeedsResponse, error) {
	if _, ok := accept[0]; ok {
		response := FeedsResponseDev{
			Feeds: []FeedInfoV2{},
		}
		for id, feedInfo := range feedInfos {
			response.Feeds = append(response.Feeds, makeFeedInfoV2(id, feedInfo, lastUpdates[id], preferredLanguages))
		}
		return response, nil
	}
	if _, ok := accept[2]; ok {
		response := FeedsResponseV2{
			Feeds: []FeedInfoV2{},
		}
		for id, feedInfo := range feedInfos {
			response.Feeds = append(response.Feeds, makeFeedInfoV2(id, feedInfo, lastUpdates[id], preferredLanguages))
		}
		return response, nil
	}
	if _, ok := accept[1]; ok {
		response := FeedsResponseV1{
			Feeds: []FeedInfoV1{},
		}
		for id, feedInfo := range feedInfos {
			response.Feeds = append(response.Feeds, makeFeedInfoV1(id, feedInfo, lastUpdates[id], preferredLanguages))
		}
		return response, nil
	}
	return FeedsResponseDev{}, AcceptError
}

func makeFeedInfoV2(id string, feedInfo traffic.FeedInfo, lastUpdate time.Time, preferredLanguages []language.Tag) FeedInfoV2 {
	descriptionTag, attributionTag := selectLanguage(feedInfo.Descriptions, feedInfo.Attributions, preferredLanguages)
	return FeedInfoV2{
		Name:        feedInfo.Name,
		Id:          id,
		Attribution: feedInfo.Attributions[attributionTag.String()],
		Description: feedInfo.Descriptions[descriptionTag.String()],
		LastUpdate:  lastUpdate.Format(traffic.DateFormat),
		QrHost:      feedInfo.QrHost,
		QrIn:        QRLocationV1(feedInfo.QrLocation),
		QrSelector:  feedInfo.QrSelector,
		ValidSince:  feedInfo.ValidSince,
		ValidTill:   feedInfo.ValidTill,
	}
}

func makeFeedInfoV1(id string, feedInfo traffic.FeedInfo, lastUpdate time.Time, preferredLanguages []language.Tag) FeedInfoV1 {
	descriptionTag, attributionTag := selectLanguage(feedInfo.Descriptions, feedInfo.Attributions, preferredLanguages)
	return FeedInfoV1{
		Name:        feedInfo.Name,
		Id:          id,
		Attribution: feedInfo.Attributions[attributionTag.String()],
		Description: feedInfo.Descriptions[descriptionTag.String()],
		LastUpdate:  lastUpdate.Format(traffic.DateTimeFormat),
	}
}
